﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Beetle.FandorinsBugBrain
{
   public partial class Net
    {

        double LearningRate=Constants.LearningRate;
      
        public double[] FindBestOut(Bettle beetle, Target[] targets, double[] output, out bool isGood, out bool isRandom)
        {
            isGood=false;
            isRandom = false;
            int min=450, max=500;
            double[] bestOutPut = new double[output.Length];
            if (Better(beetle.previousCoord, beetle.position, targets))
            {
                isGood = true;
                min = 0;
            }
            Random ran = new Random();
            if(isGood||ran.Next(0,2)==1)
            {
                int i = 0;
                for (int j = 0; j < 6; j++)
                {

                    if (output[i] > 0) bestOutPut[i] = 0.1;
                    else bestOutPut[i] = -0.1;
                    if (output[i + 1] > 0) bestOutPut[i] = 0.1;
                    else bestOutPut[i + 1] = -0.1;
                    if (output[i + 2] > 0) bestOutPut[i] = 0.1;
                    else bestOutPut[i + 2] = -0.1;
                    if (Math.Abs(output[i]) > Constants.betta && Math.Abs(output[i]) >= Math.Abs(output[i + 1]))
                        if (output[i] > 0)
                            bestOutPut[i] = Constants.rand.Next(min, max) / 1000d;
                        else
                            bestOutPut[i] = Constants.rand.Next(-max, -min) / 1000d;
                    if (Math.Abs(output[i + 1]) > Constants.betta && Math.Abs(output[i + 1]) >= Math.Abs(output[i]))
                        if (output[i + 1] > 0)
                            bestOutPut[i + 1] = Constants.rand.Next(min, max) / 1000d;
                        else
                            bestOutPut[i + 1] = Constants.rand.Next(-max, -min) / 1000d;


                    if (output[i + 2] >= 0) bestOutPut[i + 2] = Constants.rand.Next(min, max) / 1000d;
                    else bestOutPut[i + 2] = Constants.rand.Next(-max, -min) / 1000d;
                    i += 3;
                }
            }
            else
            {
                for (int i = 0; i < output.Length; i++)
                    bestOutPut[i] = Constants.rand.Next(-(Constants.RadomBorderVal), (Constants.RadomBorderVal)) / 1000d;
                isRandom = false;
            }
            return bestOutPut;
        }

        public bool Better(Position oldCoord, Position newCoord, Target[] targets)
        {
         //   if (newCoord.x == targets[0].coord.x && newCoord.y == targets[0].coord.y) return true;
          //  if (newCoord.x == targets[1].coord.x && newCoord.y == targets[1].coord.y) return false;
            //double xViewOld = Math.Cos(oldCoord.ViewAngle * (Math.PI / 180));
            #region Old
            double oldPosWithAngleX = oldCoord.x + Math.Cos(oldCoord.ViewAngle * (Math.PI / 180));
            double oldPosWithAngleY = oldCoord.y + Math.Sin(oldCoord.ViewAngle * (Math.PI / 180));
            //food
            double B1 = targets[0].coord.x - oldPosWithAngleX;
            double B2 = targets[0].coord.y - oldPosWithAngleY;
            double LengthToFood = Math.Sqrt(Math.Pow(B1, 2) + Math.Pow(B2, 2));
            //Danger
            double C1 = targets[1].coord.x - oldPosWithAngleX;
            double C2 = targets[1].coord.y - oldPosWithAngleY;
            double LengthToDanger = Math.Sqrt(Math.Pow(C1, 2) + Math.Pow(C2, 2));
            //double oldDelta = LengthToDanger -Math.Pow( LengthToFood,3);
            #endregion

            double newPosWithAngleX = newCoord.x + Math.Cos(newCoord.ViewAngle * (Math.PI / 180));
            double newPosWithAngleY = newCoord.y + Math.Sin(newCoord.ViewAngle * (Math.PI / 180));
            //food
            B1 = targets[0].coord.x - newPosWithAngleX;
            B2 = targets[0].coord.y - newPosWithAngleY;
            double newLengthToFood = Math.Sqrt(Math.Pow(B1, 2) + Math.Pow(B2, 2));
            //return newLengthToFood < LengthToFood;
            //Danger
            C1 = targets[1].coord.x - newPosWithAngleX;
            C2 = targets[1].coord.y - newPosWithAngleY;
            double newLengthToDanger = Math.Sqrt(Math.Pow(C1, 2) + Math.Pow(C2, 2));
            double foodDelta =Constants.foodCoef*(  Math.Pow(LengthToFood,2) -  Math.Pow(newLengthToFood,2));//>0
            double dangerDelta =  Constants.dangerCoef * (LengthToDanger - newLengthToDanger);//>0
            //return ((foodDelta > 0 && dangerDelta > 0) || ((foodDelta > 0) && (Math.Pow(foodDelta, 2) - dangerDelta > 0)));
           // double NewDelta = newLengthToDanger - Math.Pow( newLengthToFood,3);          
            return (foodDelta-dangerDelta > 0);
              
        }


        public double[] MakeInput(Bettle bettle, Target[] targets)
        {
            double[] result = new double[34];
            int counter = 0;
            for (int i = 0; i < 6; i++)
            {
                if (bettle.Legs[i].IsUp == 0)
                {
                    result[counter + bettle.Legs[i].State] = -0.5;
                }
                else
                {
                    result[counter + bettle.Legs[i].State] = 0.5;
                }

                counter += 3;
            }

            var target = targets.First(t=>t.weight==1);
            double angleToTarget = bettle.AngleToTarget(target);
            int step = 45/16;
            int k = 0;
            double a = 0.5, b = .25;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 1] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 2] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 3] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 4] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 5] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 6] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 7] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 8] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 9] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 10] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 11] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 12] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 13] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter +14] = a;
            if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 15] = a;
            target = targets.FirstOrDefault(t => t.weight == -1);
            if (target != null)
            {
                k = 0;
                angleToTarget = bettle.AngleToTarget(target);
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 1] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 2] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 3] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 4] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 5] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 6] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 7] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 8] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 9] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 10] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 11] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 12] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 13] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 14] = b;
                if (angleToTarget >= k * step && angleToTarget < ++k * step) result[counter + 15] = b;
            }
            return result;
        }

        
        public Bettle.Leg[] MakeLegs(Bettle bettle, double[] output)
        {
            Bettle.Leg[] result = new Bettle.Leg[6];
            int counter = 0;
            for (int i = 0; i < 6; i++)
            {
                Bettle.Leg tempLeg = new Bettle.Leg();
                tempLeg.Side = i / 3;
                if (Math.Abs(output[counter]) > Constants.betta && Math.Abs(output[counter]) >= Math.Abs(output[counter + 1]))
                {
                    if (output[counter] > 0) tempLeg.State = bettle.Legs[i].State + 1;
                    else tempLeg.State = bettle.Legs[i].State - 1;
                }
                if (Math.Abs(output[counter + 1]) > Constants.betta && Math.Abs(output[counter + 1]) > Math.Abs(output[counter]))
                {
                    if (output[counter + 1] > 0) tempLeg.State = bettle.Legs[i].State + 2;
                    else tempLeg.State = bettle.Legs[i].State - 2;
                }
                if (output[counter + 2] >= 0) tempLeg.IsUp = 1;
                else tempLeg.IsUp = 0;
                result[i] = tempLeg;
                counter += 3;
            }
            return result;
        }
       
    
        public double[] MakeOut(Bettle.Leg[] legs)
        {
            double[] result = new double[18];

            int counter = 0;

            for (int i = 0; i < 6; i++)
            {
                if (legs[i].IsUp == 0)
                {
                    result[counter + legs[i].State] = -1;
                }
                else
                {
                    result[counter + legs[i].State] = 1;
                }

                counter += 3;
            }

            return result;
        }

    }
  
}
